#include "eth/eth.h"
#include "debug.h"

#define ETH_PHY_RESET_GPIO_PORT GPIOD
#define ETH_PHY_RESET_GPIO_PIN	GPIO_PIN_3

static void eth_phy_init_reset_gpio(void);

static ETH_HandleTypeDef heth;
static uint8_t mac_addr[] = {MAC_ADDR0,MAC_ADDR1,MAC_ADDR2,MAC_ADDR3,MAC_ADDR4,MAC_ADDR5};

void eth_init(void)
{
	heth.Instance = ETH;  
  heth.Init.MACAddr = mac_addr;
  heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
  heth.Init.Speed = ETH_SPEED_100M;
  heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
  heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
  heth.Init.RxMode = ETH_RXINTERRUPT_MODE;
  heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
  heth.Init.PhyAddress = LAN8720A_PHY_ADDRESS;
	
	/* init phy reset pin */
	eth_phy_init_reset_gpio();
	/* reset phy */
	eth_phy_hard_reset();
	
	HAL_ETH_Init(&heth);

	/*开启自动协商（前面如果初始化的时候未接入网线则会link超时返回，导致未开启自动协商，热插拔功能会失效）*/
	HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_AUTONEGOTIATION);
	
	PRINTF("phy id:%08x\r\n",eth_read_phy_id());
}

void eth_start(void)
{
	HAL_ETH_Start(&heth);
}

void eth_stop(void)
{
	HAL_ETH_Stop(&heth);
}

/**
  * @brief  Initializes the ETH MSP.
  * @param  heth: ETH handle
  * @retval None
  */
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable ETHERNET clock  */
  __HAL_RCC_ETH_CLK_ENABLE();
  
  /* Enable GPIOs clocks */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();

/* Ethernet pins configuration ************************************************/
  /*
        RMII_REF_CLK ----------------------> PA1
        RMII_MDIO -------------------------> PA2
        RMII_MDC --------------------------> PC1
        RMII_MII_CRS_DV -------------------> PA7
        RMII_MII_RXD0 ---------------------> PC4
        RMII_MII_RXD1 ---------------------> PC5
        RMII_MII_RXER ---------------------> 
        RMII_MII_TX_EN --------------------> PG11
        RMII_MII_TXD0 ---------------------> PG13
        RMII_MII_TXD1 ---------------------> PG14
  */

  /* Configure PA1, PA2 and PA7 */
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStructure.Pull = GPIO_NOPULL; 
  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  /* Configure PC1, PC4 and PC5 */
  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* Configure PG11, PG13 and PG14 */
  GPIO_InitStructure.Pin =  GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
	
  /* Enable the Ethernet global Interrupt */
  HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
  HAL_NVIC_EnableIRQ(ETH_IRQn);
}

/**
  * @brief  This function handles Ethernet interrupt request.
  * @param  None
  * @retval None
  */
//void ETH_IRQHandler(void)
//{
//  HAL_ETH_IRQHandler(&heth);
//}

/**
  * @brief  Ethernet Rx Transfer completed callback
  * @param  heth: ETH handle
  * @retval None
  */
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
  
}

void eth_phy_init_reset_gpio(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
	
  __HAL_RCC_GPIOD_CLK_ENABLE();
	
	/*
		ETH_RESET -------------------------> 
	*/
  
	/* config reset gpio */
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStructure.Pull = GPIO_NOPULL;
  GPIO_InitStructure.Pin =  ETH_PHY_RESET_GPIO_PIN;
  HAL_GPIO_Init(ETH_PHY_RESET_GPIO_PORT, &GPIO_InitStructure);
}

void eth_phy_hard_reset(void)
{
	HAL_GPIO_WritePin(ETH_PHY_RESET_GPIO_PORT,ETH_PHY_RESET_GPIO_PIN,GPIO_PIN_RESET);
	HAL_Delay(PHY_RESET_DELAY);
	HAL_GPIO_WritePin(ETH_PHY_RESET_GPIO_PORT,ETH_PHY_RESET_GPIO_PIN,GPIO_PIN_SET);
	HAL_Delay(PHY_RESET_DELAY);
}

uint32_t eth_read_phy_id(void)
{
	uint32_t id1,id2;
	
	HAL_ETH_ReadPHYRegister(&heth,PHY_ID1,&id1);
	HAL_ETH_ReadPHYRegister(&heth,PHY_ID2,&id2);
	
	return ((id1 << 16) | id2);
}
